home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 21 / AACD 21.iso / AACD / Utilities / Ghostscript / src / gxfixed.h < prev    next >
Encoding:
C/C++ Source or Header  |  2001-01-01  |  10.2 KB  |  260 lines

  1. /* Copyright (C) 1989, 1995, 1996, 1997, 1998, 1999 Aladdin Enterprises.  All rights reserved.
  2.   
  3.   This file is part of AFPL Ghostscript.
  4.   
  5.   AFPL Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author or
  6.   distributor accepts any responsibility for the consequences of using it, or
  7.   for whether it serves any particular purpose or works at all, unless he or
  8.   she says so in writing.  Refer to the Aladdin Free Public License (the
  9.   "License") for full details.
  10.   
  11.   Every copy of AFPL Ghostscript must include a copy of the License, normally
  12.   in a plain ASCII text file named PUBLIC.  The License grants you the right
  13.   to copy, modify and redistribute AFPL Ghostscript, but only under certain
  14.   conditions described in the License.  Among other things, the License
  15.   requires that the copyright notice and this notice be preserved on all
  16.   copies.
  17. */
  18.  
  19. /*$Id: gxfixed.h,v 1.2 2000/09/19 19:00:37 lpd Exp $ */
  20. /* Fixed-point arithmetic for Ghostscript */
  21.  
  22. #ifndef gxfixed_INCLUDED
  23. #  define gxfixed_INCLUDED
  24.  
  25. /*
  26.  * Coordinates are generally represented internally by fixed-point
  27.  * quantities: integers lose accuracy in crucial places,
  28.  * and floating point arithmetic is slow.
  29.  */
  30. typedef long fixed;
  31. typedef ulong ufixed;        /* only used in a very few places */
  32.  
  33. #define max_fixed max_long
  34. #define min_fixed min_long
  35. #define fixed_0 0L
  36. #define fixed_epsilon 1L
  37. /*
  38.  * 12 bits of fraction provides both the necessary accuracy and
  39.  * a sufficiently large range of coordinates.
  40.  */
  41. #define _fixed_shift 12
  42. #define fixed_fraction_bits _fixed_shift
  43. #define fixed_int_bits (sizeof(fixed) * 8 - _fixed_shift)
  44. #define fixed_scale (1<<_fixed_shift)
  45. #define _fixed_rshift(x) arith_rshift(x,_fixed_shift)
  46. #define _fixed_round_v (fixed_scale>>1)
  47. #define _fixed_fraction_v (fixed_scale-1)
  48. /*
  49.  * We use a center-of-pixel filling rule; Adobe specifies that coordinates
  50.  * designate half-open regions.  Because of this, we need special rounding
  51.  * to go from a coordinate to the pixel it falls in.  We use the term
  52.  * "pixel rounding" for this kind of rounding.
  53.  */
  54. #define _fixed_pixround_v (_fixed_round_v - fixed_epsilon)
  55.  
  56. /*
  57.  * Most operations can be done directly on fixed-point quantities:
  58.  * addition, subtraction, shifting, multiplication or division by
  59.  * (integer) constants; assignment, assignment with zero;
  60.  * comparison, comparison against zero.
  61.  * Multiplication and division by floats is OK if the result is
  62.  * explicitly cast back to fixed.
  63.  * Conversion to and from int and float types must be done explicitly.
  64.  * Note that if we are casting a fixed to a float in a context where
  65.  * only ratios and not actual values are involved, we don't need to take
  66.  * the scale factor into account: we can simply cast to float directly.
  67.  */
  68. #define int2fixed(i) ((fixed)(i)<<_fixed_shift)
  69. /* Define some useful constants. */
  70. /* Avoid casts, so strict ANSI compilers will accept them in #ifs. */
  71. #define fixed_1 (fixed_epsilon << _fixed_shift)
  72. #define fixed_half (fixed_1 >> 1)
  73. /*
  74.  * On 16-bit systems, we can convert fixed variables to ints more efficiently
  75.  * than general fixed quantities.  For this reason, we define two separate
  76.  * sets of conversion macros.
  77.  */
  78. #define fixed2int(x) ((int)_fixed_rshift(x))
  79. #define fixed2int_rounded(x) ((int)_fixed_rshift((x)+_fixed_round_v))
  80. #define fixed2int_ceiling(x) ((int)_fixed_rshift((x)+_fixed_fraction_v))
  81. #define fixed_pre_pixround(x) ((x)+_fixed_pixround_v)
  82. #define fixed2int_pixround(x) fixed2int(fixed_pre_pixround(x))
  83. #define fixed_is_int(x) !((x)&_fixed_fraction_v)
  84. #if arch_ints_are_short & !arch_is_big_endian
  85. /* Do some of the shifting and extraction ourselves. */
  86. #  define _fixed_hi(x) *((const uint *)&(x)+1)
  87. #  define _fixed_lo(x) *((const uint *)&(x))
  88. #  define fixed2int_var(x)\
  89.     ((int)((_fixed_hi(x) << (16-_fixed_shift)) +\
  90.            (_fixed_lo(x) >> _fixed_shift)))
  91. #  define fixed2int_var_rounded(x)\
  92.     ((int)((_fixed_hi(x) << (16-_fixed_shift)) +\
  93.            (((_fixed_lo(x) >> (_fixed_shift-1))+1)>>1)))
  94. #  define fixed2int_var_ceiling(x)\
  95.     (fixed2int_var(x) -\
  96.      arith_rshift((int)-(_fixed_lo(x) & _fixed_fraction_v), _fixed_shift))
  97. #else
  98. /* Use reasonable definitions. */
  99. #  define fixed2int_var(x) fixed2int(x)
  100. #  define fixed2int_var_rounded(x) fixed2int_rounded(x)
  101. #  define fixed2int_var_ceiling(x) fixed2int_ceiling(x)
  102. #endif
  103. #define fixed2int_var_pixround(x) fixed2int_pixround(x)
  104. #define fixed2long(x) ((long)_fixed_rshift(x))
  105. #define fixed2long_rounded(x) ((long)_fixed_rshift((x)+_fixed_round_v))
  106. #define fixed2long_ceiling(x) ((long)_fixed_rshift((x)+_fixed_fraction_v))
  107. #define fixed2long_pixround(x) ((long)_fixed_rshift((x)+_fixed_pixround_v))
  108. #define float2fixed(f) ((fixed)((f)*(float)fixed_scale))
  109. /* Note that fixed2float actually produces a double result. */
  110. #define fixed2float(x) ((x)*(1.0/fixed_scale))
  111.  
  112. /* Rounding and truncation on fixeds */
  113. #define fixed_floor(x) ((x)&(-1L<<_fixed_shift))
  114. #define fixed_rounded(x) (((x)+_fixed_round_v)&(-1L<<_fixed_shift))
  115. #define fixed_ceiling(x) (((x)+_fixed_fraction_v)&(-1L<<_fixed_shift))
  116. #define fixed_pixround(x) (((x)+_fixed_pixround_v)&(-1L<<_fixed_shift))
  117. #define fixed_fraction(x) ((int)(x)&_fixed_fraction_v)
  118. /* I don't see how to do truncation towards 0 so easily.... */
  119. #define fixed_truncated(x) ((x) < 0 ? fixed_ceiling(x) : fixed_floor(x))
  120.  
  121. /* Define the largest and smallest integer values that fit in a fixed. */
  122. #if arch_sizeof_int == arch_sizeof_long
  123. #  define max_int_in_fixed fixed2int(max_fixed)
  124. #  define min_int_in_fixed fixed2int(min_fixed)
  125. #else
  126. #  define max_int_in_fixed max_int
  127. #  define min_int_in_fixed min_int
  128. #endif
  129.  
  130. #ifdef USE_FPU
  131. #  define USE_FPU_FIXED (USE_FPU < 0 && arch_floats_are_IEEE && arch_sizeof_long == 4)
  132. #else
  133. #  define USE_FPU_FIXED 0
  134. #endif
  135.  
  136. /*
  137.  * Define a procedure for computing a * b / c when b and c are non-negative,
  138.  * b < c, and a * b exceeds (or might exceed) the capacity of a long.
  139.  * Note that this procedure takes the floor, rather than truncating
  140.  * towards zero, if a < 0: this ensures 0 <= R < c, where R is the remainder.
  141.  *
  142.  * It's really annoying that C doesn't provide any way to get at
  143.  * the double-length multiply/divide instructions that almost all hardware
  144.  * provides....
  145.  */
  146. fixed fixed_mult_quo(P3(fixed A, fixed B, fixed C));
  147.  
  148. /*
  149.  * Transforming coordinates involves multiplying two floats, or a float
  150.  * and a double, and then converting the result to a fixed.  Since this
  151.  * operation is so common, we provide an alternative implementation of it
  152.  * on machines that use IEEE floating point representation but don't have
  153.  * floating point hardware.  The implementation may be in either C or
  154.  * assembler.
  155.  */
  156.  
  157. /*
  158.  * The macros all use R for the (fixed) result, FB for the second (float)
  159.  * operand, and dtemp for a temporary double variable.  The work is divided
  160.  * between the two macros of each set in order to avoid bogus "possibly
  161.  * uninitialized variable" messages from slow-witted compilers.
  162.  *
  163.  * For the case where the first operand is a float (FA):
  164.  *    code = CHECK_FMUL2FIXED_VARS(R, FA, FB, dtemp);
  165.  *    if (code < 0) ...
  166.  *    FINISH_FMUL2FIXED_VARS(R, dtemp);
  167.  *
  168.  * For the case where the first operand is a double (DA):
  169.  *    code = CHECK_DFMUL2FIXED_VARS(R, DA, FB, dtemp);
  170.  *    if (code < 0) ...;
  171.  *    FINISH_DFMUL2FIXED_VARS(R, dtemp);
  172.  */
  173. #if USE_FPU_FIXED && arch_sizeof_short == 2
  174. #define NEED_SET_FMUL2FIXED
  175. int set_fmul2fixed_(P3(fixed *, long, long));
  176. #define CHECK_FMUL2FIXED_VARS(vr, vfa, vfb, dtemp)\
  177.   set_fmul2fixed_(&vr, *(const long *)&vfa, *(const long *)&vfb)
  178. #define FINISH_FMUL2FIXED_VARS(vr, dtemp)\
  179.   DO_NOTHING
  180. int set_dfmul2fixed_(P4(fixed *, ulong, long, long));
  181. #  if arch_is_big_endian
  182. #  define CHECK_DFMUL2FIXED_VARS(vr, vda, vfb, dtemp)\
  183.      set_dfmul2fixed_(&vr, ((const ulong *)&vda)[1], *(const long *)&vfb, *(const long *)&vda)
  184. #  else
  185. #  define CHECK_DFMUL2FIXED_VARS(vr, vda, vfb, dtemp)\
  186.      set_dfmul2fixed_(&vr, *(const ulong *)&vda, *(const long *)&vfb, ((const long *)&vda)[1])
  187. #  endif
  188. #define FINISH_DFMUL2FIXED_VARS(vr, dtemp)\
  189.   DO_NOTHING
  190.  
  191. #else /* don't bother */
  192.  
  193. #undef NEED_SET_FMUL2FIXED
  194. #define CHECK_FMUL2FIXED_VARS(vr, vfa, vfb, dtemp)\
  195.   (dtemp = (vfa) * (vfb),\
  196.    (f_fits_in_bits(dtemp, fixed_int_bits) ? 0 :\
  197.     gs_note_error(gs_error_limitcheck)))
  198. #define FINISH_FMUL2FIXED_VARS(vr, dtemp)\
  199.   vr = float2fixed(dtemp)
  200. #define CHECK_DFMUL2FIXED_VARS(vr, vda, vfb, dtemp)\
  201.   CHECK_FMUL2FIXED_VARS(vr, vda, vfb, dtemp)
  202. #define FINISH_DFMUL2FIXED_VARS(vr, dtemp)\
  203.   FINISH_FMUL2FIXED_VARS(vr, dtemp)
  204.  
  205. #endif
  206.  
  207. /*
  208.  * set_float2fixed_vars(R, F) does the equivalent of R = float2fixed(F):
  209.  *      R is a fixed, F is a float or a double.
  210.  * set_fixed2float_var(R, V) does the equivalent of R = fixed2float(V):
  211.  *      R is a float or a double, V is a fixed.
  212.  * set_ldexp_fixed2double(R, V, E) does the equivalent of R=ldexp((double)V,E):
  213.  *      R is a double, V is a fixed, E is an int.
  214.  * R and F must be variables, not expressions; V and E may be expressions.
  215.  */
  216. #if USE_FPU_FIXED
  217. int set_float2fixed_(P3(fixed *, long, int));
  218. int set_double2fixed_(P4(fixed *, ulong, long, int));
  219.  
  220. # define set_float2fixed_vars(vr,vf)\
  221.     (sizeof(vf) == sizeof(float) ?\
  222.      set_float2fixed_(&vr, *(const long *)&vf, fixed_fraction_bits) :\
  223.      set_double2fixed_(&vr, ((const ulong *)&vf)[arch_is_big_endian],\
  224.                ((const long *)&vf)[1 - arch_is_big_endian],\
  225.                fixed_fraction_bits))
  226. long fixed2float_(P2(fixed, int));
  227. void set_fixed2double_(P3(double *, fixed, int));
  228.  
  229. /*
  230.  * We need the (double *)&vf cast to prevent compile-time error messages,
  231.  * even though the call will only be executed if vf has the correct type.
  232.  */
  233. # define set_fixed2float_var(vf,x)\
  234.     (sizeof(vf) == sizeof(float) ?\
  235.      (*(long *)&vf = fixed2float_(x, fixed_fraction_bits), 0) :\
  236.      (set_fixed2double_((double *)&vf, x, fixed_fraction_bits), 0))
  237. #define set_ldexp_fixed2double(vd, x, exp)\
  238.   set_fixed2double_(&vd, x, -(exp))
  239. #else
  240. # define set_float2fixed_vars(vr,vf)\
  241.     (f_fits_in_bits(vf, fixed_int_bits) ? (vr = float2fixed(vf), 0) :\
  242.      gs_note_error(gs_error_limitcheck))
  243. # define set_fixed2float_var(vf,x)\
  244.     (vf = fixed2float(x), 0)
  245. # define set_ldexp_fixed2double(vd, x, exp)\
  246.     discard(vd = ldexp((double)(x), exp))
  247. #endif
  248.  
  249. /* A point with fixed coordinates */
  250. typedef struct gs_fixed_point_s {
  251.     fixed x, y;
  252. } gs_fixed_point;
  253.  
  254. /* A rectangle with fixed coordinates */
  255. typedef struct gs_fixed_rect_s {
  256.     gs_fixed_point p, q;
  257. } gs_fixed_rect;
  258.  
  259. #endif /* gxfixed_INCLUDED */
  260.